Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_message_sending_failures.py

Displaying Raw • Download


tests/backend/test_message_sending_failures.py v4.7.0-rc.4 (448cd46c) Text, 8.92 KB

T8b949e# SPDX-License-Identifier: 0BSD

Tff7b72import T7ee787asyncio
Tff7b72import T7ee787json
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3AsyncMockTb4b4b4, Te6edf3MagicMockTb4b4b4, Te6edf3PropertyMockTb4b4b4, Te6edf3patch

Tff7b72import T7ee787LXMF
Tff7b72import T7ee787pytest

Tff7b72from T7ee787meshchatxT7ee787.T7ee787meshchat Tff7b72import Te6edf3ReticulumMeshChat
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787reticulum_pathfinding Tff7b72import Te6edf3OutboundPathOutcome


Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffmock_appTb4b4b4(Tb4b4b4)Tb4b4b4:
T8b949e# Use __new__ to avoid full initialization
Te6edf3app Tff7b72= Te6edf3ReticulumMeshChatTff7b72.Td2a8ff__new__Tb4b4b4(Te6edf3ReticulumMeshChatTb4b4b4)
Te6edf3appTff7b72.Td2a8ffcurrent_context Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffconfig Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffdatabase Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffreticulum Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffmessage_router Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ff_await_transport_path Tff7b72= Te6edf3AsyncMockTb4b4b4(
Te6edf3return_valueTff7b72=Te6edf3OutboundPathOutcomeTb4b4b4(Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffreused_valid_pathTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffget_current_icon_hash Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3return_valueTff7b72=Tff7b72NoneTb4b4b4)
Te6edf3appTff7b72.Td2a8ffdb_upsert_lxmf_message Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffwebsocket_broadcast Tff7b72= Te6edf3AsyncMockTb4b4b4(Tb4b4b4)
Te6edf3appTff7b72.Td2a8ff_is_contact Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3return_valueTff7b72=Tff7b72FalseTb4b4b4)
Te6edf3appTff7b72.Td2a8ff_convert_webm_opus_to_ogg Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3side_effectTff7b72=Tff7b72lambda Te6edf3bTb4b4b4: Te6edf3bTb4b4b4)
Te6edf3appTff7b72.Td2a8ffhandle_lxmf_message_progress Tff7b72= Te6edf3AsyncMockTb4b4b4(Tb4b4b4)

T8b949e# Setup context
Te6edf3ctx Tff7b72= Te6edf3appTff7b72.Td2a8ffcurrent_context
Te6edf3ctxTff7b72.Td2a8ffmessage_router Tff7b72= Te6edf3appTff7b72.Td2a8ffmessage_router
Te6edf3ctxTff7b72.Td2a8ffdatabase Tff7b72= Te6edf3appTff7b72.Td2a8ffdatabase
Te6edf3ctxTff7b72.Td2a8ffconfig Tff7b72= Te6edf3appTff7b72.Td2a8ffconfig
Te6edf3ctxTff7b72.Td2a8fflocal_lxmf_destination Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3ctxTff7b72.Td2a8fflocal_lxmf_destinationTff7b72.Td2a8ffhexhash Tff7b72= Ta5d6ff"Ta5d6fflocal_hashTa5d6ff"
Te6edf3ctxTff7b72.Td2a8ffforwarding_manager Tff7b72= Tff7b72None

Tff7b72return Te6edf3app


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_send_message_no_path_identity_recall_failsTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3destination_hash Tff7b72= Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff16
Te6edf3mock_appTff7b72.Td2a8ffrecall_identity Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3return_valueTff7b72=Tff7b72NoneTb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ExceptionTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffCould not find path to destinationTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3mock_appTff7b72.Td2a8ffsend_messageTb4b4b4(
Te6edf3destination_hashTff7b72=Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72=Ta5d6ff"Ta5d6ffhiTa5d6ff"Tb4b4b4,
Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_send_message_immediate_exception_in_routerTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3destination_hash Tff7b72= Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff16
Te6edf3fake_identity Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)

Te6edf3mock_appTff7b72.Td2a8ffmessage_routerTff7b72.Td2a8ffhandle_outboundTff7b72.Td2a8ffside_effect Tff7b72= Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffRouter failureTa5d6ff"Tb4b4b4)

Te6edf3mock_appTff7b72.Td2a8ffrecall_identity Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3return_valueTff7b72=Te6edf3fake_identityTb4b4b4)
Tff7b72with Tb4b4b4(
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.RNS.DestinationTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.LXMF.LXMessageTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ExceptionTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffRouter failureTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3mock_appTff7b72.Td2a8ffsend_messageTb4b4b4(
Te6edf3destination_hashTff7b72=Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72=Ta5d6ff"Ta5d6ffhiTa5d6ff"Tb4b4b4,
Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_on_lxmf_sending_failed_updates_stateTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3mock_msg Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3specTff7b72=Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffstate Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILED
Te6edf3mock_msgTff7b72.Td2a8fftry_propagation_on_fail Tff7b72= Tff7b72False

Te6edf3mock_appTff7b72.Td2a8ffon_lxmf_sending_state_updated Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)

Tff7b72from T7ee787meshchatxT7ee787.T7ee787meshchat Tff7b72import Te6edf3ReticulumMeshChat

Te6edf3ReticulumMeshChatTff7b72.Td2a8ffon_lxmf_sending_failedTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3mock_msgTb4b4b4)

Te6edf3mock_appTff7b72.Td2a8ffon_lxmf_sending_state_updatedTff7b72.Td2a8ffassert_called_once_withTb4b4b4(
Te6edf3mock_msgTb4b4b4, Te6edf3contextTff7b72=Te6edf3mock_appTff7b72.Td2a8ffcurrent_context
Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_propagation_fallback_on_failureTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3mock_msg Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3specTff7b72=Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffstate Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILED
Te6edf3mock_msgTff7b72.Td2a8fftry_propagation_on_fail Tff7b72= Tff7b72True
Te6edf3mock_msgTff7b72.Td2a8ffsource_hash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffsourceTa5d6ff"

Te6edf3mock_appTff7b72.Td2a8ffsend_failed_message_via_propagation_node Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_appTff7b72.Td2a8ffon_lxmf_sending_state_updated Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)

Tff7b72from T7ee787meshchatxT7ee787.T7ee787meshchat Tff7b72import Te6edf3ReticulumMeshChat

Te6edf3ReticulumMeshChatTff7b72.Td2a8ffon_lxmf_sending_failedTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3mock_msgTb4b4b4)

Te6edf3mock_appTff7b72.Td2a8ffsend_failed_message_via_propagation_nodeTff7b72.Td2a8ffassert_called_once_withTb4b4b4(
Te6edf3mock_msgTb4b4b4, Te6edf3contextTff7b72=Te6edf3mock_appTff7b72.Td2a8ffcurrent_context
Tb4b4b4)
Te6edf3mock_appTff7b72.Td2a8ffon_lxmf_sending_state_updatedTff7b72.Td2a8ffassert_called_once_withTb4b4b4(
Te6edf3mock_msgTb4b4b4, Te6edf3contextTff7b72=Te6edf3mock_appTff7b72.Td2a8ffcurrent_context
Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_handle_lxmf_message_progress_failure_broadcastTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3mock_msg Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffhash Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTff7b72.Td2a8ffreturn_value Tff7b72= Ta5d6ff"Ta5d6ffmsg_hash_hexTa5d6ff"
Te6edf3mock_msgTff7b72.Td2a8ffprogress Tff7b72= T79c0ff0.0
Te6edf3mock_msgTff7b72.Td2a8ffdelivery_attempts Tff7b72= T79c0ff1

T8b949e# State sequence: FAILED (first iteration should terminate loop)
Tffa657typeTb4b4b4(Te6edf3mock_msgTb4b4b4)Tff7b72.Td2a8ffstate Tff7b72= Te6edf3PropertyMockTb4b4b4(Te6edf3return_valueTff7b72=Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILEDTb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffmethod Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffDIRECT

Tff7b72with Tb4b4b4(
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.convert_lxmf_state_to_stringTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Ta5d6ff"Ta5d6fffailedTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx.meshchat.convert_lxmf_method_to_stringTa5d6ff"Tb4b4b4,
Te6edf3return_valueTff7b72=Ta5d6ff"Ta5d6ffdirectTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx.meshchat.convert_lxmf_message_to_dictTa5d6ff"Tb4b4b4,
Te6edf3return_valueTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffhexTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fffailedTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffasyncio.sleepTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3asyncioTff7b72.Td2a8ffFutureTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72as Te6edf3mock_sleepTb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3mock_sleepTff7b72.Td2a8ffreturn_valueTff7b72.Td2a8ffset_resultTb4b4b4(Tff7b72NoneTb4b4b4)

Tff7b72from T7ee787meshchatxT7ee787.T7ee787meshchat Tff7b72import Te6edf3ReticulumMeshChat

Tff7b72await Te6edf3ReticulumMeshChatTff7b72.Td2a8ffhandle_lxmf_message_progressTb4b4b4(
Te6edf3mock_appTb4b4b4, Te6edf3mock_msgTb4b4b4, Te6edf3contextTff7b72=Te6edf3mock_appTff7b72.Td2a8ffcurrent_context
Tb4b4b4)

T8b949e# Verify update was called
Te6edf3mock_appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffmessagesTff7b72.Td2a8ffupdate_lxmf_message_stateTff7b72.Td2a8ffassert_calledTb4b4b4(Tb4b4b4)
T8b949e# Verify websocket broadcast was called
Te6edf3mock_appTff7b72.Td2a8ffwebsocket_broadcastTff7b72.Td2a8ffassert_calledTb4b4b4(Tb4b4b4)

Te6edf3args Tff7b72= Te6edf3mock_appTff7b72.Td2a8ffwebsocket_broadcastTff7b72.Td2a8ffcall_argsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3argsTb4b4b4)
Tff7b72assert Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fflxmf_message_state_updatedTa5d6ff"
Tff7b72assert Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6fflxmf_messageTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fffailedTa5d6ff"


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_handle_lxmf_message_progress_continues_while_propagation_fallback_pendingTb4b4b4(
Te6edf3mock_appTb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3mock_msg Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffhash Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTff7b72.Td2a8ffreturn_value Tff7b72= Ta5d6ff"Ta5d6ffmsg_hash_hexTa5d6ff"
Te6edf3mock_msgTff7b72.Td2a8ffprogress Tff7b72= T79c0ff0.0
Te6edf3mock_msgTff7b72.Td2a8ffdelivery_attempts Tff7b72= T79c0ff1
Te6edf3mock_msgTff7b72.Td2a8fftry_propagation_on_fail Tff7b72= Tff7b72True
Te6edf3mock_msgTff7b72.Td2a8ffstate Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILED
Te6edf3mock_msgTff7b72.Td2a8ffmethod Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffDIRECT

Te6edf3iteration Tff7b72= T79c0ff0

Tff7b72async Tff7b72def Td2a8ffcounting_sleepTb4b4b4(Te6edf3_durationTb4b4b4)Tb4b4b4:
Tff7b72nonlocal Te6edf3iteration
Te6edf3iteration Tff7b72+Tff7b72= T79c0ff1
Tff7b72if Te6edf3iteration Tff7b72== T79c0ff2Tb4b4b4:
Te6edf3mock_msgTff7b72.Td2a8fftry_propagation_on_fail Tff7b72= Tff7b72False
Te6edf3mock_msgTff7b72.Td2a8ffstate Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffSENT
Te6edf3mock_msgTff7b72.Td2a8ffmethod Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffPROPAGATED

Tff7b72def Td2a8ffstate_to_strTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3msgTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILEDTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6fffailedTa5d6ff"
Tff7b72if Te6edf3msgTff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffSENTTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffsentTa5d6ff"
Tff7b72return Ta5d6ff"Ta5d6ffunknownTa5d6ff"

Tff7b72with Tb4b4b4(
Te6edf3patchTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx.meshchat.convert_lxmf_state_to_stringTa5d6ff"Tb4b4b4, Te6edf3side_effectTff7b72=Te6edf3state_to_str
Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx.meshchat.convert_lxmf_method_to_stringTa5d6ff"Tb4b4b4,
Te6edf3side_effectTff7b72=Tff7b72lambda Te6edf3mTb4b4b4: Tb4b4b4(
Ta5d6ff"Ta5d6ffpropagatedTa5d6ff" Tff7b72if Te6edf3mTff7b72.Td2a8ffmethod Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffPROPAGATED Tff7b72else Ta5d6ff"Ta5d6ffdirectTa5d6ff"
Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx.meshchat.convert_lxmf_message_to_dictTa5d6ff"Tb4b4b4,
Te6edf3side_effectTff7b72=Tff7b72lambda Tff7b72*Te6edf3aTb4b4b4, Tff7b72*Tff7b72*Te6edf3kTb4b4b4: Tb4b4b4{
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffhexTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fffailedTa5d6ff" Tff7b72if Te6edf3aTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffstate Tff7b72== Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffFAILED Tff7b72else Ta5d6ff"Ta5d6ffsentTa5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffasyncio.sleepTa5d6ff"Tb4b4b4, Te6edf3side_effectTff7b72=Te6edf3counting_sleepTb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72from T7ee787meshchatxT7ee787.T7ee787meshchat Tff7b72import Te6edf3ReticulumMeshChat

Tff7b72await Te6edf3ReticulumMeshChatTff7b72.Td2a8ffhandle_lxmf_message_progressTb4b4b4(
Te6edf3mock_appTb4b4b4, Te6edf3mock_msgTb4b4b4, Te6edf3contextTff7b72=Te6edf3mock_appTff7b72.Td2a8ffcurrent_context
Tb4b4b4)

Tff7b72assert Te6edf3iteration Tff7b72== T79c0ff2
T8b949e# Initial failed update, one more while propagation fallback is still pending,
T8b949e# then the final propagated update after the second sleep.
Tff7b72assert Te6edf3mock_appTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffmessagesTff7b72.Td2a8ffupdate_lxmf_message_stateTff7b72.Td2a8ffcall_count Tff7b72== T79c0ff3


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_send_message_db_upsert_failure_still_broadcastsTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
T8b949e# If db_upsert fails, we want to know if it's caught or if it crashes send_message.
T8b949e# Actually, send_message doesn't have a try-except around db_upsert_lxmf_message.
T8b949e# If it fails, the whole send_message fails, which returns 503 to frontend.

Te6edf3destination_hash Tff7b72= Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff16
Te6edf3fake_identity Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)

Te6edf3mock_appTff7b72.Td2a8ffdb_upsert_lxmf_messageTff7b72.Td2a8ffside_effect Tff7b72= Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffDB ErrorTa5d6ff"Tb4b4b4)

Tff7b72with Tb4b4b4(
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.RNS.Identity.recallTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3fake_identityTb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.RNS.DestinationTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.LXMF.LXMessageTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ExceptionTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffDB ErrorTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3mock_appTff7b72.Td2a8ffsend_messageTb4b4b4(
Te6edf3destination_hashTff7b72=Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72=Ta5d6ff"Ta5d6ffhiTa5d6ff"Tb4b4b4,
Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_send_message_await_path_timeoutTb4b4b4(Te6edf3mock_appTb4b4b4)Tb4b4b4:
Te6edf3mock_appTff7b72.Td2a8ff_await_transport_path Tff7b72= Te6edf3AsyncMockTb4b4b4(
Te6edf3return_valueTff7b72=Te6edf3OutboundPathOutcomeTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffnew_path_requestedTa5d6ff"Tb4b4b4, Tff7b72TrueTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3destination_hash Tff7b72= Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff16

T8b949e# Even if _await_transport_path returns False, it continues to recall identity
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.RNS.Identity.recallTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ExceptionTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffCould not find path to destinationTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3mock_appTff7b72.Td2a8ffsend_messageTb4b4b4(
Te6edf3destination_hashTff7b72=Te6edf3destination_hashTb4b4b4,
Te6edf3contentTff7b72=Ta5d6ff"Ta5d6ffhiTa5d6ff"Tb4b4b4,
Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────